package com.netty.bfport.netty.server;

import com.alibaba.fastjson.JSONObject;
import com.netty.bfport.http.common.kafka.Producer;
import com.netty.bfport.http.domain.DO.MessageDO;
import com.netty.bfport.http.domain.dto.TUserMachineDTO;
import com.netty.bfport.http.mapper.MsgMapper;
import com.netty.bfport.http.mapper.UserMachineMapper;
import io.netty.channel.*;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.util.concurrent.GlobalEventExecutor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Date;

/**
 * @Author: zhaoyang05
 * @Data: 2022/3/1 11:07
 * @Description
 * 信息处理
 */
@Slf4j
@Component
@ChannelHandler.Sharable
public class NettyServerHandler extends ChannelInboundHandlerAdapter {
    //心跳阈值
    @Value("${hight}")
    private  String HIGHT;

    //心跳最小值
    @Value("${low}")
    private  String LOW;

    private static NettyServerHandler handler;
    @Resource
    Producer producer;
    @Resource
    MsgMapper msgMapper;
    @Resource
    UserMachineMapper userMachineMapper;
    //APP客户端
    public static ChannelGroup channelsApp = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
    //web客户端
    public static ChannelGroup channelsWeb = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
    //即将推送的消息列表
    public static volatile JSONObject message = new JSONObject();
//    static {
//        message.put("qweawsd",JSONObject.parseObject("{\"4b1a49ad\":{\"createTime\":1651913567232,\"header\":\"2132ewq\",\"heart\":\"100\",\"humidity\":\"0257\",\"machineId\":\"002\",\"name\":\"刘能\",\"status\":2,\"temperature\":\"0.253\",\"userId\":\"36b482185c0944a9a6d663da57756a35\"}}"));
//        message.put("asd",JSONObject.parseObject("{\"4b1a49ad\":{\"createTime\":1651913567232,\"header\":\"2132ewq\",\"heart\":\"100\",\"humidity\":\"0257\",\"machineId\":\"002\",\"name\":\"迪丽热巴\",\"status\":2,\"temperature\":\"0.253\",\"userId\":\"36b482185c0944a9a6d663da57756a35\"}}"));
//        message.put("ret",JSONObject.parseObject("{\"4b1a49ad\":{\"createTime\":1651913567232,\"header\":\"2132ewq\",\"heart\":\"100\",\"humidity\":\"0257\",\"machineId\":\"002\",\"name\":\"古力娜扎\",\"status\":2,\"temperature\":\"0.253\",\"userId\":\"36b482185c0944a9a6d663da57756a35\"}}"));
//        message.put("qweawsvcxd",JSONObject.parseObject("{\"4b1a49ad\":{\"createTime\":1651913567232,\"header\":\"2132ewq\",\"heart\":\"100\",\"humidity\":\"0257\",\"machineId\":\"002\",\"name\":\"马儿扎哈\",\"status\":2,\"temperature\":\"0.253\",\"userId\":\"36b482185c0944a9a6d663da57756a35\"}}"));
//        message.put("qweawsryd",JSONObject.parseObject("{\"4b1a49ad\":{\"createTime\":1651913567232,\"header\":\"2132ewq\",\"heart\":\"100\",\"humidity\":\"0257\",\"machineId\":\"002\",\"name\":\"斯巴达\",\"status\":2,\"temperature\":\"0.253\",\"userId\":\"36b482185c0944a9a6d663da57756a35\"}}"));
//        message.put("qweawslkd",JSONObject.parseObject("{\"4b1a49ad\":{\"createTime\":1651913567232,\"header\":\"2132ewq\",\"heart\":\"100\",\"humidity\":\"0257\",\"machineId\":\"002\",\"name\":\"迪迦\",\"status\":2,\"temperature\":\"0.253\",\"userId\":\"36b482185c0944a9a6d663da57756a35\"}}"));
//    }

    /**
     * 客户端连接会触发
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        log.info("Channel active......");
        SocketChannel channel = (SocketChannel )ctx.channel();
        log.info("客户端：" +channel.localAddress() + "连接成功");
        ctx.writeAndFlush("worcome");
    }

    /**
     * 心跳处理
     * */
    private void heart(ChannelHandlerContext ctx){
        ctx.write("心跳" + "\r\n");
        log.info("心跳");
        ctx.flush();
    }

    /**
     * 消息处理
     * */
    private void message(ChannelHandlerContext ctx, JSONObject msg){
        ctx.write("消息");
        log.info("客户端发送的消息：{}" , msg);
        MessageDO messageDO = messageeNrichmentHandler(msg);
        messageToZero(messageDO);
        message.put(ctx.channel().id().toString(),messageDO);
        producer.send(messageDO);
        ctx.flush();
    }

    /**
     * 如果心率，湿度，温度入参为null时处理为0
     * */
    public void messageToZero(MessageDO messageDO){
        if (messageDO.getHeart()==null){
            messageDO.setHeart("0");
        }
        if (messageDO.getHumidity()==null){
            messageDO.setHumidity("0");
        }
        if (messageDO.getTemperature()==null){
            messageDO.setTemperature("0");
        }
    }

    /**
     * 信息富化处理器
     * TODO:需要将数据库查询这里优化，不建议此处走数据库IO
     * */
    private MessageDO messageeNrichmentHandler(JSONObject msg){
        //设备id
        String id = msg.getString("userId");
        MessageDO messageDO = msgMapper.userMsg(id);
        TUserMachineDTO userMachineDTO = new TUserMachineDTO();
        userMachineDTO.setMachineId(msg.getString("machineId"));
        userMachineDTO.setUserId(id);
        userMachineMapper.userMachineAdd(userMachineDTO);
        JSONObject data = msg.getJSONObject("data");
        //心率
        String heart = data.getString("heart");
        //用户id
        messageDO.setUserId(id);
        //机器编码
        messageDO.setMachineId(msg.getString("machineId"));
        messageDO.setHeart(heart);
        //湿度
        messageDO.setHumidity(data.getString("humidity"));
        //温度
        messageDO.setTemperature(data.getString("temperature"));
        messageDO.setStatus(1);//心率正常
        if (heart.compareTo(HIGHT)>0){
            messageDO.setStatus(2);//心率过高
        }else if (LOW.compareTo(heart)>0){
            messageDO.setStatus(0); //心率过低
        }
        messageDO.setCreateTime(new Date());
        return messageDO;
    }

    /**
     * 客户端分组
     * */
    private void addGroup(ChannelHandlerContext ctx,String client){
        ChannelId id = ctx.channel().id();
        if ("0".equals(client)){
            Channel channel = channelsApp.find(id);
            if (channel==null){
                channelsApp.add(ctx.channel());
            }
        }else if("1".equals(client)) {
            Channel channel = channelsWeb.find(id);
            if (channel == null) {
                channelsWeb.add(ctx.channel());
            }
        }
    }

    /**
     * 客户端发消息会触发
     */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
//        log.info("服务器收到消息: {}", msg);
        JSONObject jsonObject = JSONObject.parseObject(msg.toString());
        String status = jsonObject.getString("status");
        String client = jsonObject.getString("client");//0app,1web
        addGroup(ctx,client);
        log.info("App端客户端数量:" + channelsApp.size());
        log.info("Web端客户端数量:" + channelsWeb.size());
        if (status.equals("0")){
            //心跳
            heart(ctx);
        }
        if (client.equals("0")){
            if (status.equals("1")){
                //消息
                JSONObject data = jsonObject.getJSONObject("data");
                message(ctx, jsonObject);
            }
        }

    }

    /**
     * 发生异常触发
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        cause.printStackTrace();
        Channel channel = channelsApp.find(ctx.channel().id());
        if (channel==null){
            Channel channel1 = channelsWeb.find(ctx.channel().id());
            channelsWeb.remove(channel1);
            message.remove(ctx.channel().id().toString());
        }else {
            channelsApp.remove(channel);
            message.remove(ctx.channel().id().toString());
        }
        ctx.close();
    }

    /**
     * 客户端断开连接后处理器
     * */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        Channel channel = channelsApp.find(ctx.channel().id());
        if (channel==null){
            Channel channel1 = channelsWeb.find(ctx.channel().id());
            channelsWeb.remove(channel1);
            message.remove(ctx.channel().id().toString());
        }else {
            channelsApp.remove(channel);
            message.remove(ctx.channel().id().toString());
        }

        log.info("客户端断开链接" + ctx.channel().localAddress().toString());
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        Channel channel = channelsApp.find(ctx.channel().id());
        if (channel==null){
            Channel channel1 = channelsWeb.find(ctx.channel().id());
            channelsWeb.remove(channel1);
            message.remove(ctx.channel().id().toString());
        }else {
            channelsApp.remove(channel);
            message.remove(ctx.channel().id().toString());
        }

        log.info("客户端断开链接" + ctx.channel().localAddress().toString());
    }
}
